import stackless
import time
import struct
#import pygame
import network
import pyglet_display as display
import pyglet_input as input
import physics
from pyglet import clock
from sglibrary import Actor, Vector

class World(Actor):
    def __init__(self, players={}):
        self.players = players
        #self.objects = objects
        self.actions = {"PJOIN": self.player_join, "DATA": self.data,
                        "OJOIN": self.object_join, "QUIT": self.quit,
                        "SEND": self.send}
        self.net_actions = [self.player_join]
        #display.init()
        Actor.__init__(self)

    def process_message(self, action, args):
        print action
        self.actions[action](*args)

    def data(self, player, data):
        try:
            self.players[player].send(("NET",
                    struct.unpack("B", data[0]), data[1:]))
        except KeyError:
            print "Possible Cracker ip:%s", player

    def player_join(self, player, channel):
        if player == "127.0.0.1":
            #pygame.time.set_timer(pygame.USEREVENT, 100)
            self.user = channel
            stackless.tasklet(self.main)()
            return
        self.players[player] = channel

    def player_leave(self, player):
        del(self.players[player])

    def object_join(self, channel):
        self.objects.append(channel)

    def check_events(self):
        pass
        #if pygame.event.get(pygame.USEREVENT):
        #    print "send_data", self.players
        #    self.user.send(("SEND", ()))

    def send(self, data):
        print "sending"
        self.send_chan.send(data)
        print "sent"

    def quit(self):
        exit()

    def main(self):
        while True:
            #self.check_events()
            #print "main"
            self.window.dispatch_events()
            self.window.clear()
            self.user.send(("DRAW", ()))
            for player in self.players:
                player.send(("DRAW", ()))
            self.window.flip()
            #display.render()
            #print "schedule"
            stackless.schedule()

## class Sector(Actor):
##     def __init__(self, players={}, asteroids={}):
##         self.players = players
##         self.asteroids = asteroids
##         self.positons = dict([(key, (0,0,0)) for key in self.players])
##         self.actions = {"set_pos": self.set_positions}
##         Actor.__init__(self)

##     def set_positions(self, player, position):
##         self.positions[player] = position

##     def send_actor_postions(self):
##         for player in self.players:
##             player.send(self.positions)

##     def process_message(self, action, args):
##         self.actions[action](*args)

class Player(Actor):
    def __init__(self, position, world, name, call_list, window):
        self.position = position
        self.world = world
        self.name = name
        self.call_list = call_list
        self.window = window
        self.actions = {"shot": self.shot,
                        "DATA": self.received,
                        "NET": self.user_action,
                        "DRAW": self.draw}
        self.methods = [self.shot]
        self.last_time = 0
        Actor.__init__(self)
        world.send(("PJOIN", (self.name, self.channel)))
        
    def draw(self):
        self.window.draw(self.call_list)

    def received(self):
        pass

    def process_message(self, action, args):
        #print action, args
        self.actions[action](*args)

    def user_action(self, method, data):
        self.methods[method](data)

    def dispatch(self, message):
        pass

    def shot(self, position, direction):
        if time.time() > self.last_time:
            Shot(time, position, direction, world)
            self.last_time = time

from pyglet import image

class User(Player):
    def __init__(self, position, world, name, hud, window):
        """hud is a call list for the users HUD"""
        self.input = input.Keyboard(window, self.quit)
        self.spaceship = physics.SpaceShip(self.input)
        self.starfield = display.StarField(1500, (1.0, 1.0, 1.0),
                                            -100, [0,0], (640,480))
        self.hud = display.make_hud()
        self.window = window
	#pic = image.load("textures/gray.png")
        #self.square = display.Square()
        #display.init()
        #self.camera = display.Camera(self.spaceship)#, (1280,1024))
        #self.input = input.Keyboard(xchannel, zchannel, self.quit)
        Player.__init__(self, position, world, name, hud, window)
        self.actions["SEND"] = self.send

    def draw(self):
        #self.window.dispatch_events()
        self.spaceship.update()
        #self.window.draw_list(self.hud)
        #self.window.draw_image(self.pic)
        self.window.transform(self.spaceship.position,
                              self.spaceship.rotation)
        self.starfield.draw()
        #display.start_draw(self.spaceship.position,
        #                   self.spaceship.rotation,
        #                   self.call_list)
        #self.starfield.draw()
        #display.draw_pic()
        #self.square.draw()

    def send(self):
        #print struct.pack("<fff fff", *self.spaceship.get_pos_or())
        #print "sending, struct", self.world
        self.world.send(("SEND",
                        (struct.pack("<fff fff", *self.spaceship.get_pos_or()),)))
        #print "sent, struct"

    def quit(self):
        print "quitting"
        print clock.get_fps()
        self.window.close()
        raise SystemExit

    def main(self):
        #self.c = pygame.time.Clock()
        while True:
            #self.c.tick(200)
            self.input.process_events()
            #stackless.schedule()
            #self.camera.draw()
            stackless.schedule()

class Shot(Actor):
    def __init__(self, time, position, direction, world):
        print self, time, position, direction
        self.position = Vector(position)
        self.direction = Vector(direction)
        self.world = world
        Actor.__init__(self)
        world.send("OJOIN", self.channel)

    def set_position(self, rho):
        return self.position + rho * self.direction

class Asteroid(Actor):
    pass

#if __name__ == "__main__":
def main(w):
    """This function is called by main.py to start the
    whole thing off."""
    w.window = display.GameWindow()
    #w = World()
    #c = display.make_crosshair()
    #print "c", c
    u = User(Vector(0,0,0), w.channel, "127.0.0.1", None, w.window)
    stackless.tasklet(u.main)()
    stackless.run()
